package com.lysh.aliHttp.utils;

import com.lysh.aliHttp.ClientConfiguration;
import com.lysh.aliHttp.common.ResponseMessage;
import com.lysh.aliHttp.common.exception.InconsistentException;
import com.lysh.aliHttp.model.Callback;
import com.lysh.aliHttp.model.ObjectMetadata;
import com.lysh.aliHttp.model.ResponseHeaderOverrides;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author liyishan
 * @date 2023/5/5 09:47
 * @apiNote
 */

public class OSSUtils {
    public static final ResourceManager OSS_RESOURCE_MANAGER = ResourceManager.getInstance("oss");
    public static final ResourceManager COMMON_RESOURCE_MANAGER = ResourceManager.getInstance("common");
    private static final String BUCKET_NAMING_REGEX = "^[a-z0-9][a-z0-9_\\-]{1,61}[a-z0-9]$";

    public OSSUtils() {
    }

    public static boolean validateBucketName(String bucketName) {
        return bucketName == null ? false : bucketName.matches("^[a-z0-9][a-z0-9_\\-]{1,61}[a-z0-9]$");
    }

    public static void ensureBucketNameValid(String bucketName) {
        if (!validateBucketName(bucketName)) {
            throw new IllegalArgumentException(OSS_RESOURCE_MANAGER.getFormattedString("BucketNameInvalid", new Object[]{bucketName}));
        }
    }

    public static boolean validateObjectKey(String key) {
        if (key != null && key.length() != 0) {
            byte[] bytes = null;
            try {
                bytes = key.getBytes("utf-8");
            } catch (UnsupportedEncodingException var4) {
                return false;
            }

            char[] keyChars = key.toCharArray();
            char firstChar = keyChars[0];
            if (firstChar != '/' && firstChar != '\\') {
                return bytes.length > 0 && bytes.length < 1024;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public static void ensureObjectKeyValid(String key) {
        if (!validateObjectKey(key)) {
            throw new IllegalArgumentException(OSS_RESOURCE_MANAGER.getFormattedString("ObjectKeyInvalid", new Object[]{key}));
        }
    }

    public static void ensureLiveChannelNameValid(String liveChannelName) {
        if (!validateObjectKey(liveChannelName)) {
            throw new IllegalArgumentException(OSS_RESOURCE_MANAGER.getFormattedString("LiveChannelNameInvalid", new Object[]{liveChannelName}));
        }
    }

    public static URI determineFinalEndpoint(URI endpoint, String bucket, ClientConfiguration clientConfig) {
        try {
            StringBuilder conbinedEndpoint = new StringBuilder();
            conbinedEndpoint.append(String.format("%s://", endpoint.getScheme()));
            conbinedEndpoint.append(buildCanonicalHost(endpoint, bucket, clientConfig));
            conbinedEndpoint.append(endpoint.getPort() != -1 ? String.format(":%s", endpoint.getPort()) : "");
            conbinedEndpoint.append(endpoint.getPath());
            return new URI(conbinedEndpoint.toString());
        } catch (URISyntaxException var4) {
            throw new IllegalArgumentException(var4.getMessage(), var4);
        }
    }

    private static String buildCanonicalHost(URI endpoint, String bucket, ClientConfiguration clientConfig) {
        String host = endpoint.getHost();
        boolean isCname = false;
        if (clientConfig.isSupportCname()) {
            isCname = cnameExcludeFilter(host, clientConfig.getCnameExcludeList());
        }

        StringBuffer cannonicalHost = new StringBuffer();
        if (bucket != null && !isCname && !clientConfig.isSLDEnabled()) {
            cannonicalHost.append(bucket).append(".").append(host);
        } else {
            cannonicalHost.append(host);
        }

        return cannonicalHost.toString();
    }

    private static boolean cnameExcludeFilter(String hostToFilter, List<String> excludeList) {
        if (hostToFilter != null && !hostToFilter.trim().isEmpty()) {
            String canonicalHost = hostToFilter.toLowerCase();
            Iterator i = excludeList.iterator();

            String excl;
            do {
                if (!i.hasNext()) {
                    return true;
                }

                excl = (String)i.next();
            } while(!canonicalHost.endsWith(excl));

            return false;
        } else {
            throw new IllegalArgumentException("Host name can not be null.");
        }
    }

    public static String determineResourcePath(String bucket, String key, boolean sldEnabled) {
        return sldEnabled ? makeResourcePath(bucket, key) : makeResourcePath(key);
    }

    public static String makeResourcePath(String key) {
        return key != null ? urlEncodeKey(key) : null;
    }

    public static String makeResourcePath(String bucket, String key) {
        return bucket != null ? bucket + "/" + (key != null ? urlEncodeKey(key) : "") : null;
    }

    private static String urlEncodeKey(String key) {
        StringBuffer resultUri = new StringBuffer();
        String[] keys = key.split("/");
        resultUri.append(HttpUtil.urlEncode(keys[0], "utf-8"));

        int i;
        for(i = 1; i < keys.length; ++i) {
            resultUri.append("/").append(HttpUtil.urlEncode(keys[i], "utf-8"));
        }

        if (key.endsWith("/")) {
            for(i = key.length() - 1; i >= 0 && key.charAt(i) == '/'; --i) {
                resultUri.append("/");
            }
        }

        return resultUri.toString();
    }

    public static void populateRequestMetadata(Map<String, String> headers, ObjectMetadata metadata) {
        Map<String, Object> rawMetadata = metadata.getRawMetadata();
        String key;
        if (rawMetadata != null) {
            Iterator i$ = rawMetadata.entrySet().iterator();

            while(i$.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry)i$.next();
                if (entry.getKey() != null && entry.getValue() != null) {
                    key = (String)entry.getKey();
                    if (key != null) {
                        key = key.trim();
                    }

                    if (key != null) {
                        key = key.trim();
                    }

                    headers.put(key, key);
                }
            }
        }

        Map<String, String> userMetadata = metadata.getUserMetadata();
        if (userMetadata != null) {
            Iterator i$ = userMetadata.entrySet().iterator();

            while(i$.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry)i$.next();
                if (entry.getKey() != null && entry.getValue() != null) {
                    key = (String)entry.getKey();
                    String value = (String)entry.getValue();
                    if (key != null) {
                        key = key.trim();
                    }

                    if (value != null) {
                        value = value.trim();
                    }

                    headers.put("x-oss-meta-" + key, value);
                }
            }
        }

    }

    public static void addHeader(Map<String, String> headers, String header, String value) {
        if (value != null) {
            headers.put(header, value);
        }

    }

    public static void addDateHeader(Map<String, String> headers, String header, Date value) {
        if (value != null) {
            headers.put(header, DateUtil.formatRfc822Date(value));
        }

    }

    public static void addStringListHeader(Map<String, String> headers, String header, List<String> values) {
        if (values != null && !values.isEmpty()) {
            headers.put(header, join(values));
        }

    }

    public static void removeHeader(Map<String, String> headers, String header) {
        if (header != null && headers.containsKey(header)) {
            headers.remove(header);
        }

    }

    public static String join(List<String> strings) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;

        for(Iterator i$ = strings.iterator(); i$.hasNext(); first = false) {
            String s = (String)i$.next();
            if (!first) {
                sb.append(", ");
            }

            sb.append(s);
        }

        return sb.toString();
    }

    public static String trimQuotes(String s) {
        if (s == null) {
            return null;
        } else {
            s = s.trim();
            if (s.startsWith("\"")) {
                s = s.substring(1);
            }

            if (s.endsWith("\"")) {
                s = s.substring(0, s.length() - 1);
            }

            return s;
        }
    }

    public static void populateResponseHeaderParameters(Map<String, String> params, ResponseHeaderOverrides responseHeaders) {
        if (responseHeaders != null) {
            if (responseHeaders.getCacheControl() != null) {
                params.put("response-cache-control", responseHeaders.getCacheControl());
            }

            if (responseHeaders.getContentDisposition() != null) {
                params.put("response-content-disposition", responseHeaders.getContentDisposition());
            }

            if (responseHeaders.getContentEncoding() != null) {
                params.put("response-content-encoding", responseHeaders.getContentEncoding());
            }

            if (responseHeaders.getContentLangauge() != null) {
                params.put("response-content-language", responseHeaders.getContentLangauge());
            }

            if (responseHeaders.getContentType() != null) {
                params.put("response-content-type", responseHeaders.getContentType());
            }

            if (responseHeaders.getExpires() != null) {
                params.put("response-expires", responseHeaders.getExpires());
            }
        }

    }

    public static void safeCloseResponse(ResponseMessage response) {
        try {
            response.close();
        } catch (IOException var2) {
        }

    }

    public static void mandatoryCloseResponse(ResponseMessage response) {
        try {
            response.abort();
        } catch (IOException var2) {
        }

    }

    public static long determineInputStreamLength(InputStream instream, long hintLength) {
        return hintLength > 0L && instream.markSupported() ? hintLength : -1L;
    }

    public static long determineInputStreamLength(InputStream instream, long hintLength, boolean useChunkEncoding) {
        if (useChunkEncoding) {
            return -1L;
        } else {
            return hintLength > 0L && instream.markSupported() ? hintLength : -1L;
        }
    }

    public static String joinETags(List<String> eTags) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;

        for(Iterator i$ = eTags.iterator(); i$.hasNext(); first = false) {
            String eTag = (String)i$.next();
            if (!first) {
                sb.append(", ");
            }

            sb.append(eTag);
        }

        return sb.toString();
    }

    public static String composeRequestAuthorization(String accessKeyId, String signature) {
        return "OSS " + accessKeyId + ":" + signature;
    }

    public static String jsonizeCallback(Callback callback) {
        StringBuffer jsonBody = new StringBuffer();
        jsonBody.append("{");
        jsonBody.append("\"callbackUrl\":\"" + callback.getCallbackUrl() + "\"");
        if (callback.getCallbackHost() != null && !callback.getCallbackHost().isEmpty()) {
            jsonBody.append(",\"callbackHost\":\"" + callback.getCallbackHost() + "\"");
        }

        jsonBody.append(",\"callbackBody\":\"" + callback.getCallbackBody() + "\"");
        if (callback.getCalbackBodyType() == Callback.CalbackBodyType.JSON) {
            jsonBody.append(",\"callbackBodyType\":\"application/json\"");
        } else if (callback.getCalbackBodyType() == Callback.CalbackBodyType.URL) {
            jsonBody.append(",\"callbackBodyType\":\"application/x-www-form-urlencoded\"");
        }

        jsonBody.append("}");
        return jsonBody.toString();
    }

    public static String jsonizeCallbackVar(Callback callback) {
        StringBuffer jsonBody = new StringBuffer();
        jsonBody.append("{");
        Iterator i$ = callback.getCallbackVar().entrySet().iterator();

        while(i$.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry)i$.next();
            if (entry.getKey() != null && entry.getValue() != null) {
                if (!jsonBody.toString().equals("{")) {
                    jsonBody.append(",");
                }

                jsonBody.append("\"" + (String)entry.getKey() + "\":\"" + (String)entry.getValue() + "\" ");
            }
        }

        jsonBody.append("}");
        return jsonBody.toString();
    }

    public static void ensureCallbackValid(Callback callback) {
        if (callback != null) {
            CodingUtils.assertStringNotNullOrEmpty(callback.getCallbackUrl(), "Callback.callbackUrl");
            CodingUtils.assertParameterNotNull(callback.getCallbackBody(), "Callback.callbackBody");
        }

    }

    public static void populateRequestCallback(Map<String, String> headers, Callback callback) {
        if (callback != null) {
            String jsonCb = jsonizeCallback(callback);
            String base64Cb = BinaryUtil.toBase64String(jsonCb.getBytes());
            headers.put("x-oss-callback", base64Cb);
            if (callback.hasCallbackVar()) {
                String jsonCbVar = jsonizeCallbackVar(callback);
                String base64CbVar = BinaryUtil.toBase64String(jsonCbVar.getBytes());
                base64CbVar = base64CbVar.replaceAll("\n", "").replaceAll("\r", "");
                headers.put("x-oss-callback-var", base64CbVar);
            }
        }

    }

    public static void checkChecksum(Long clientChecksum, Long serverChecksum, String requestId) {
        if (clientChecksum != null && serverChecksum != null && !clientChecksum.equals(serverChecksum)) {
            throw new InconsistentException(clientChecksum, serverChecksum, requestId);
        }
    }
}
